#include "commonModeloProtocolo.h"

ModeloProtocolo::ModeloProtocolo() {
	codigo = 0;
	longitudArgumento = 0;
	argumento = NULL;
}

ModeloProtocolo::~ModeloProtocolo() {
	if (argumento != NULL) delete[] argumento;
}

void ModeloProtocolo::extraerCampo(std::string& operacion, 
				   				  std::string& campoProtocolo) {
	int offset = 0;
	offset = operacion.find(' ');
	campoProtocolo = operacion.substr(0, offset);
	operacion.erase(0, offset + 1);
}

char *ModeloProtocolo::getArgumento() const {
    return argumento;
}

char ModeloProtocolo::getCodigo() const {
    return codigo;
}

unsigned int ModeloProtocolo::getLongitudArgumento() const {
    return longitudArgumento;
}

void ModeloProtocolo::setArgumento(char *argumento) {
    this->argumento = argumento;
}

void ModeloProtocolo::setCodigo(char codigo) {
    this->codigo = codigo;
}

void ModeloProtocolo::setLongitudArgumento(unsigned int longitudArgumento) {
    this->longitudArgumento = longitudArgumento;
}

void ModeloProtocolo::stringToProtocolo(std::string& operacion) {
	std::string campoProtocolo;
	char * ptr = NULL;
	
	extraerCampo(operacion, campoProtocolo);  // Identifico codigo.
	
	if (campoProtocolo[UBICACION_CODIGO] == OPERACION_INSERTAR)
		codigo = CODIGO_INSERTAR;
	else if (campoProtocolo[UBICACION_CODIGO] == OPERACION_ELIMINAR)
		codigo = CODIGO_ELIMINAR;
	else if (campoProtocolo[UBICACION_CODIGO] == OPERACION_CONSULTAR)
		codigo = CODIGO_CONSULTAR;
	else
		codigo = CODIGO_INVALIDO;

	longitudArgumento = operacion.size();
	argumento = new char[longitudArgumento];
	ptr = argumento;

	if (codigo == CODIGO_INSERTAR) {  // Argumento para una insercion.
		extraerCampo(operacion, campoProtocolo);  // Identifico Argumento Clave.
		memcpy(argumento, campoProtocolo.c_str(), campoProtocolo.size());
		ptr += campoProtocolo.size();

		const char separador = SEPARADOR_CLAVE_VALOR;
		memcpy(ptr, &separador, sizeof(char));

		// Identifico Argumento Valor.
		ptr += sizeof(char);
		memcpy(ptr, operacion.c_str(), campoProtocolo.size());
	}
	else if (codigo == CODIGO_ELIMINAR || codigo == CODIGO_CONSULTAR) {
		// Lo que queda de la operacion corresponde a la clave.
		memcpy(ptr, operacion.c_str(), longitudArgumento);
	}
	else
		memset(ptr, 0, longitudArgumento);
}

void ModeloProtocolo::hidratar(char* datosIniciales,
							   char* argumentos) {
		unsigned int longitudArgumento = 0;
		char *ptr = datosIniciales;

		ptr += sizeof(char);
		longitudArgumento = *(unsigned int*)(ptr);

		argumento = new char[longitudArgumento];

		this->codigo = *(char*)datosIniciales;
		this->longitudArgumento = longitudArgumento;

		memcpy(this->argumento, argumentos, longitudArgumento);
}

char* ModeloProtocolo::serializar() {
	char * serializacion = new char[sizeof(int) + 
									sizeof(char) + 
									longitudArgumento];
	char *ptr = serializacion;

	memcpy(ptr, &codigo, sizeof(char));
	ptr += sizeof(char);
	memcpy(ptr, &longitudArgumento, sizeof(int));
	ptr += sizeof(int);
	memcpy(ptr, argumento, longitudArgumento);

	return serializacion;
}
